package utils

import (
	"os"
	"path/filepath"
	"strconv"
	"time"

	"github.com/joho/godotenv"
)

// ConfigGetter 配置获取器接口
type ConfigGetter interface {
	GetString(key string, defaultValue string) string
	GetInt(key string, defaultValue int) int
	GetBool(key string, defaultValue bool) bool
	GetDuration(key string, defaultValue time.Duration) time.Duration
}

// Config 配置管理器
type Config struct {
	envPath string
	envMap  map[string]string
	loaded  bool
}

// NewConfig 创建新的配置管理器
func NewConfig() *Config {
	return &Config{
		envPath: ".env",
		envMap:  make(map[string]string),
		loaded:  false,
	}
}

// NewConfigWithPath 创建指定路径的配置管理器
func NewConfigWithPath(envPath string) *Config {
	return &Config{
		envPath: envPath,
		envMap:  make(map[string]string),
		loaded:  false,
	}
}

// Load 加载配置文件
func (c *Config) Load() error {
	// 加载.env文件
	if err := c.loadEnvFile(); err != nil {
		return err
	}

	c.loaded = true
	return nil
}

// loadEnvFile 加载.env文件
func (c *Config) loadEnvFile() error {
	// 清空现有映射
	c.envMap = make(map[string]string)

	// 获取当前工作目录
	wd, err := os.Getwd()
	if err != nil {
		return err
	}

	envPath := filepath.Join(wd, c.envPath)

	// 使用godotenv直接读取文件内容到map，不设置环境变量
	envMap, err := godotenv.Read(envPath)
	if err != nil {
		return err
	}

	// 将.env文件内容加载到内部映射
	for key, value := range envMap {
		c.envMap[key] = value
	}

	return nil
}

// loadEnv 加载指定路径的.env文件
func (c *Config) loadEnv(envPath string) error {
	// 清空现有映射
	c.envMap = make(map[string]string)

	// 使用godotenv直接读取文件内容到map
	envMap, err := godotenv.Read(envPath)
	if err != nil {
		return err
	}

	// 将.env文件内容加载到内部映射
	for key, value := range envMap {
		c.envMap[key] = value
	}

	c.loaded = true
	return nil
}

// GetString 获取字符串配置值
func (c *Config) GetString(key string, defaultValue string) string {
	// 检查是否已加载
	if !c.loaded {
		if err := c.Load(); err != nil {
			return defaultValue
		}
	}

	// 只从.env文件映射中获取
	if value, exists := c.envMap[key]; exists && value != "" {
		return value
	}

	// 使用默认值
	return defaultValue
}

// GetInt 获取整数配置值
func (c *Config) GetInt(key string, defaultValue int) int {
	strValue := c.GetString(key, "")
	if strValue == "" {
		return defaultValue
	}

	if value, err := strconv.Atoi(strValue); err == nil {
		return value
	}

	return defaultValue
}

// GetBool 获取布尔配置值
func (c *Config) GetBool(key string, defaultValue bool) bool {
	strValue := c.GetString(key, "")
	if strValue == "" {
		return defaultValue
	}

	if value, err := strconv.ParseBool(strValue); err == nil {
		return value
	}

	return defaultValue
}

// GetDuration 获取时间配置值
func (c *Config) GetDuration(key string, defaultValue time.Duration) time.Duration {
	strValue := c.GetString(key, "")
	if strValue == "" {
		return defaultValue
	}

	if value, err := time.ParseDuration(strValue); err == nil {
		return value
	}

	return defaultValue
}

// MustGetString 必须获取字符串配置值，如果不存在则panic
func (c *Config) MustGetString(key string) string {
	value := c.GetString(key, "")
	if value == "" {
		panic("required config key '" + key + "' not found")
	}
	return value
}

// MustGetInt 必须获取整数配置值，如果不存在则panic
func (c *Config) MustGetInt(key string) int {
	value := c.GetInt(key, 0)
	if value == 0 && c.GetString(key, "") == "" {
		panic("required config key '" + key + "' not found")
	}
	return value
}

// Set 设置配置值（仅用于测试）
func (c *Config) Set(key, value string) {
	c.envMap[key] = value
	c.loaded = true
}
